//
//  PSFilterWhisterAfterDeclarerMove.m
//  PrefCore
//
//  Created by Sergey on 6/20/14.
//  Copyright (c) 2014 Play-on-smart. All rights reserved.
//

#import "PSFilter.h"
#import "PSFilterUtil.h"

static PSCard* GetLowestBeatCard(
    PSEvaluator *evaluator
,   PSTrickHash trick
,   PSHandHash candidates
,   PSPlayerId playerId
,   uint8_t handIndex
,   PSCardSuit trump) {
    PSCard* res = nil;
    for (PSCardHash h = [evaluator startWithCandidates:candidates]
    ;   h != 0
    ;   h = [evaluator nextWithCandidates:candidates andCurrent:h]) {
        PSCard *c = [PSCard cardWithHash:h];
        trick = PSTrickAddCardPlayer(trick, playerId, c.compressed);
        if (PSTrickWinner(trick, trump) == playerId && (res == nil || c.rank < res.rank)) {
            res = c;
        }
        trick = PSTrickRemoveLastCard(trick);
    }
    return res;
}

PSHandHash PSFilterWhisterAfterDeclarerMove(
    PSEvaluator* evaluator
,   PSHandHash candidates
,   PSPlayerId player
,   PSTrickHash trick
,   PSCardSuit trump
,   uint8_t handIndex
,   PSPlayerId declarer
) {
    PSHandHash res = 0;
    PSCard *lbc = GetLowestBeatCard(evaluator, trick, candidates, player, handIndex, trump);
    PSHandHash lc = PSFilterGetLowestCandidates(candidates);
    if (handIndex == 1) { // hand 1 means first move was made by declarer
        if (lbc == nil) {
            res = lc;
        } else {
            res = PSHandWithOneCard(lbc);
            // get declarer's card
            PSCard *highest = PSTrickHighestCard(trick, trump);
            // add lowest candidates only if rank difference is greater than 1,
            // otherwise partner couldn't have lower beat card than current player
            if (highest.suit != lbc.suit || lbc.rank > highest.rank+1) {
                res = PSHandAddHand(res, lc);
            }
        }
    } else if (handIndex == 2) { // the player should not "beat" his partner's card
        res = (lbc == nil || PSTrickWinner(trick, trump) != declarer) ? lc : PSHandWithOneCard(lbc);
    }
    return res == 0 ? candidates : res;
}
